#ifndef SLAVE_H_
#define SLAVE_H_

#include <Poco/Net/ServerSocket.h>
using Poco::Net::ServerSocket;

#include <Poco/Net/DialogSocket.h>
using Poco::Net::DialogSocket;

#include <string>
using std::string;

#include "command/command.h"
using Commands::Command;
using Commands::NotImplemented;

#include "command/commandfactory.h"
using Commands::CommandFactory;

#include <Poco/Runnable.h>
using Poco::Runnable;

#include <Poco/Thread.h>
using Poco::Thread;

#include "command/commandqueue.h"


/**
 * This class represents the slave machine.
 *
 */
class Slave : public Runnable {
public:
	/**
	 * Constructor
	 * @param port The port on which the slave will be listening
	 * @param queue A queue for commands. Not yet implemented.
	 *
	 */
	Slave( int port, CommandQueue* queue = 0);

	/**
	 * Destructor.
	 */
	virtual ~Slave();

	/**
	 * Start the slave. 
	 */
	void run();
	
	/**
	 * Stops the slave machine.
	 */
	void stop();

	/**
	 * Run the command
	 *
	 * @param command Command to be run
	 */
	void executeCommand(Command* command);

	/**
	 * Pushes a command on the queue
	 * @param cmd The command that needs to be pushed on the queue.
	 */
	void push_up(Command* cmd);

private:
	/**
	 * A subclass that handles the connection
	 */
	class ConnectionHandler : public Runnable
	{
		public:
			/**
			 * Constructs a ConnectionHandler on a certain socket.
			 * @param connection A socket-based connection
			 * @param parent A pointer that points to the slave.
			 */
			ConnectionHandler(DialogSocket* connection, Slave* parent);
			~ConnectionHandler();
			void run();
			Thread _handler;
		private:
			DialogSocket* _sock;
			Slave* _parent;

	};

	vector<ConnectionHandler*> fHandlers;

	//! Socket for accepting connections
	ServerSocket * fServerSocket;

	//! Factory to build the commands with
	CommandFactory fCommFac;

	/**
	 * Queue that contains all the commands that need to be executed.
	 */
	CommandQueue* fQueue;

	/**
	 * The "current connection" socket. This should be connected to a Master socket.
	 */
	DialogSocket* fCurConn;

	/**
	 * The port where you can reach this slave. If he does not answer, just use a whip.
	 */
	UInt16 fPort;

	bool _connected;

};

#endif /*SLAVE_H_*/
